# -*- coding:utf-8 -*-
import os,sys
import re
import traceback
import time
sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)), os.pardir))
import supeanut_config
from CommonLib.mylog import mylog
from CommonLib.PageCrawler.UrlAccess import UrlAccess
from CommonLib.StockTool import StockTool


'''
作者：supeanut
创建时间：2016-xx-xx xx:xx:xx
功能描述：
	xxx
	xxxxx
相关配置：
	supeanut_config.XXX
历史改动：
	2016-xx-xx: xxxxxx
'''
class ExRightsAPI:
	# init what
	def __init__(self):
		self.stock_tool = StockTool()
		self.valid_check_len = 6
		self.timeout = 10
		self.try_max = 5
		self.codec = "gbk"
		self.sina_baseurl = "http://vip.stock.finance.sina.com.cn/corp/go.php/vISSUE_ShareBonus/stockid/%s.phtml"
		# 接口返回字段提取股票代码
		self.table1_RE = re.compile(r'<table id="sharebonus_1">[\s\S]*?</table>')
		self.table2_RE = re.compile(r'<table id="sharebonus_2">[\s\S]*?</table>')
		self.tbody_RE = re.compile(r'(?<=<tbody>)[\s\S]*?(?=</tbody>)')
		self.tr_RE = re.compile(r'(?<=<tr>)[\s\S]*?(?=</tr>)')
		self.td_RE = re.compile(r'(?<=<td>)[\s\S]*?(?=</td>)')
		self.date_RE = re.compile(r'^[0-9]{4}-[01][0-9]-[0123][0-9]$')
		self.value_RE = re.compile(r'^[0-9]+(\.[0-9]*)?$')
		
	# 完整url访问并解码，尝试一次
	# 返回body部分（unicode）
	def access_sina(self, url):
		log = mylog('DataAPI.SinaAPI.access_sina', None)
		accessor = UrlAccess()
		accessor.set_timeout(self.timeout)
		flag, response = accessor.get_response(url, 'GET')
		if flag is False:
			log.exception('Exception Logged')
			return False, response
		try:
			body = response['body']
			# 解码
			body = body.decode(self.codec)
		except:
			log.exception('Exception Logged')
			return False, 'decodec failed, or noformal response'
		return True, body
	
	# 处理接口返回str数据，返回标准日内数据格式dict（utf-8）
	def process_response(self, response_str, stock_sample_code):
		log = mylog('DataAPI.ExRights.process_response', None)
		try:
			fenhong_list = []
			peigu_list = []
			# 处理分红
			log.info('begin to process:%s'%stock_sample_code)
			table1 = self.table1_RE.search(response_str)
			if table1 is None:
				log.warning('table1 is None')
			table1_str = table1.group(0)
			table1_tbody = self.tbody_RE.search(table1_str)
			if table1_tbody is None:
				log.warning('table1_tbody is None')
			table1_tbody_str = table1_tbody.group(0)
			tr_list = self.tr_RE.findall(table1_tbody_str)
			if len(tr_list) == 0:
				log.warning('no tr in table')
			for tr_str in tr_list:
				tr_dict = {}
				td_list = self.td_RE.findall(tr_str)
				if len(td_list) == 0 or len(td_list) != 9:
					log.warning('tdlen invalid')
					continue
				jindu = td_list[4]
				if jindu == u'实施':
					jindu = u'suc'
				elif jindu == u'预案':
					jindu = u'pre'
				elif jindu == u'不分配':
					jindu = u'no'
				else:
					jindu = u'no match'
				tr_dict['public_date'] = td_list[0]
				tr_dict['songgu'] = str(float(td_list[1])/10.0).decode('utf-8')
				tr_dict['zhuanzen'] = str(float(td_list[2])/10.0).decode('utf-8')
				tr_dict['paixi'] = str(float(td_list[3])/10.0).decode('utf-8')
				tr_dict['jingdu'] = jindu
				tr_dict['chuquan_date'] = td_list[5]
				tr_dict['dengji_date'] = td_list[6]
				tr_dict['honggushangshi_date'] = td_list[7]
				if jindu == u'suc':
					# 只记录已实施的
					fenhong_list.append(tr_dict)
			# 处理配股
			table2 = self.table2_RE.search(response_str)
			if table2 is None:
				log.warning('table2 is None')
			table2_str = table2.group(0)
			table2_tbody = self.tbody_RE.search(table2_str)
			if table2_tbody is None:
				log.warning('table2_tbody is None')
			table2_tbody_str = table2_tbody.group(0)
			tr_list = self.tr_RE.findall(table2_tbody_str)
			if len(tr_list) == 0:
				log.warning('no tr in table')
			for tr_str in tr_list:
				tr_dict = {}
				td_list = self.td_RE.findall(tr_str)
				if len(td_list) == 0 or len(td_list) != 11:
					log.warning('td_len invalid')
					continue
				tr_dict['public_date'] = td_list[0]
				tr_dict['peigu_num'] = str(float(td_list[1])/10.0).decode('utf-8')
				tr_dict['peigu_price'] = str(float(td_list[2])).decode('utf-8')
				tr_dict['chuquan_date'] = td_list[4]
				tr_dict['dengji_date'] = td_list[5]
				tr_dict['pay_start_date'] = td_list[6][:10]
				tr_dict['pay_end_date'] = td_list[7]
				tr_dict['peigushangshi_date'] = td_list[8]
				peigu_list.append(tr_dict)
		except:
			log.error(traceback.format_exc())
			return False, 'failed to extract exData from sina'
		flag, msg = self.combine_sina_result(peigu_list, fenhong_list, stock_sample_code)
		if flag is False:
			return False, msg
		return True, msg

	def code_date_in(self, stock_sample_code, pub_date, all_list):
		for record in all_list:
			if stock_sample_code == record[0] and pub_date == record[1]:
				return True
		return False

	def checkParticular(self, fenhong_item, stock_sample_code):
		log = mylog('DataAPI.ExRights.checkParticular', None)
		pub_date = fenhong_item['public_date'].encode('utf-8')
		dengji_record = [['600556','2009-10-27'],['000520','2014-07-24'],['000751','2013-12-26'],['002608','2016-12-22'],['000732','2009-07-28'],['000035','2012-11-28'],\
			['000719','2011-06-23'],['000972','2013-02-19']]
		ignore_record = [['000155','2016-12-10'],['600572','2004-06-30'],['600065','2006-12-27']]
		if self.code_date_in(stock_sample_code, pub_date, dengji_record):
			dengji_date = fenhong_item['dengji_date'].encode('utf-8')
			if dengji_date <> '--':
				log.warning("warning: %s: trans to dengji_date, pub date:%s"%(stock_sample_code,pub_date))
				return True, dengji_date
			else:
				log.warning("warning: %s: dengji_date is --"%stock_sample_code)
				return False, 'dengji_date is --'
		if self.code_date_in(stock_sample_code, pub_date, ignore_record):
			log.warning("warning: %s: ingore cur item,pub date:%s"%(stock_sample_code,pub_date))
			return False, 'ingore cur item'
		else:
			log.warning("warning: %s: no suitable process -- now"%stock_sample_code)
			return False, 'no suitable process -- now'
	
	def combine_sina_result(self, peigu_list, fenhong_list, stock_sample_code):
		# 除权日,送股数,增股数,派息金额,配股数,配股价
		try:
			result_all = []
			chuquan_date_list = []
			chuquan_date_index = []
			for fenhong_item in fenhong_list:
				temp_list = []
				chuquan_date = fenhong_item[u'chuquan_date'].encode('utf-8')
				if chuquan_date == '--':
					chuquan_date = fenhong_item[u'honggushangshi_date'].encode('utf-8')	
					if chuquan_date == '--':
						flag, chuquan_date = self.checkParticular(fenhong_item, stock_sample_code)
						if flag is False:
							# ignore the cur fenhong_item
							continue
				chuquan_date_list.append(chuquan_date)
				temp_list.append(chuquan_date)
				temp_list.append(fenhong_item[u'songgu'].encode('utf-8'))
				temp_list.append(fenhong_item[u'zhuanzen'].encode('utf-8'))
				temp_list.append(fenhong_item[u'paixi'].encode('utf-8'))
				temp_list.append('--')
				temp_list.append('--')
				result_all.append(temp_list)
			for peigu_item in peigu_list:
				chuquan_date = peigu_item[u'chuquan_date'].encode('utf-8')
				if chuquan_date in chuquan_date_list:
					result_all[chuquan_date_list.index(chuquan_date)][4] = peigu_item[u'peigu_num'].encode('utf-8')
					result_all[chuquan_date_list.index(chuquan_date)][5] = peigu_item[u'peigu_price'].encode('utf-8')
				else:
					temp_list = []
					temp_list.append(peigu_item[u'chuquan_date'].encode('utf-8'))
					temp_list.append('--')
					temp_list.append('--')
					temp_list.append('--')
					temp_list.append(peigu_item[u'peigu_num'].encode('utf-8'))
					temp_list.append(peigu_item[u'peigu_price'].encode('utf-8'))
					result_all.append(temp_list)
			result_all.sort(key=lambda k:k[0])
		except:
			return False, traceback.format_exc()
		return True, result_all
		
	# 格式验证
	def format_check(self, result_list, stock_sample_code):
		if result_list == []:
			return True, 'no need to check empty list'
		for one_item in result_list:
			# 验证列数
			if len(one_item) <> self.valid_check_len:
				return False, 'one line must has %d items'%self.valid_check_len
			# 验证date
			date_str = one_item[0]
			c = self.date_RE.match(date_str)
			if c is None:
				return False, 'date not valid: %s'%date_str
			# 验证数字
			for value_str in one_item[1:]:
				if value_str == "--":
					continue
				c = self.value_RE.match(value_str)
				if c is None:
					return False, 'value not valid: %s'%value_str
			return True, 'suc'

	# 附带格式验证	
	def get_exRights(self, source="sina", stock_sample_code="000001"):
		log = mylog('DataAPI.ExRights.get_exRights', None)
		access_str = self.sina_baseurl%stock_sample_code
		# 访问接口，尝试多次
		try_count = 0
		try_flag = False
		while try_count < self.try_max:
			try_count += 1
			if source == 'sina':
				flag, response = self.access_sina(access_str)
			else:
				return False, 'not valid source:%s'%source
			if flag is True:
				try_flag = True
				break
			log.warning(response)
			# 访问失败，休10秒
			time.sleep(10)
		if try_flag is False:
			log.error('reach try max, no response')
			return False, 'reach try max, no response'
		# 正则提取复权数据
		flag, result_list = self.process_response(response, stock_sample_code)
		if flag is False:
			return False, result_list
		flag, msg = self.format_check(result_list, stock_sample_code)
		if flag is False:
			return False, msg
		return True, result_list

if __name__ == '__main__':
	obj = ExRightsAPI()
	stock_obj = StockTool()
	flag, msg = obj.get_exRights("sina", '000155')
	print msg
	exit(0)
	flag, stocks = stock_obj.get_all_stock_code('all')
	for stock in stocks:
		flag, msg = obj.get_exRights("sina", stock)
		print msg
		time.sleep(10)
